﻿using System;
using System.Collections.Generic;
using System.Linq;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using NETDeob.Core.Engine;

namespace NETDeob.Core.Deobfuscators.Confuser._1_7
{
    internal class Anti_Debug : IRoutine
    {
        #region Locals

        private MethodDef _antiDebugMethod;

        #endregion

        #region Routine Information

        public string Description
        {
            get { return "Remove Anti-Debug Confusion"; }
        }

        public Dictionary<Func<bool>, string> Phases
        {
            get
            {
                return new Dictionary<Func<bool>, string>
                {
                    {Phase1, "Detection"},
                    {Phase2, "Removal"}
                };
            }
        }

        #endregion

        #region Phases

        private Boolean Phase1()
        {
            try
            {
                var cctor = Settings.TargetAssemblyDef.Modules[0].Types[0].Methods[0];

                foreach (var instruction in cctor.Body.Instructions.Where(instruction => instruction.OpCode == OpCodes.Call))
                {
                    try
                    {
                        var methodDef = (MethodDef)instruction.Operand;

                        if (!methodDef.HasBody || methodDef.Parameters.Count != 0) continue;

                        _antiDebugMethod = methodDef;
                        break;
                    }
                    catch (Exception exception)
                    {
                        Logger.Exception(exception.Message, 3);
                    }
                }

                
                return _antiDebugMethod != null;
            }
            catch (Exception exception)
            {
                Logger.Exception(exception.Message, 2);
                return false;
            }
        }

        private Boolean Phase2()
        {
            try
            {
                Settings.TargetAssemblyDef.Modules[0].Types.Remove(_antiDebugMethod.DeclaringType);

                return true;
            }
            catch (Exception exception)
            {
                Logger.Exception(exception.Message, 2);
                return false;
            }
        }

        #endregion
    }
}